import { Injectable, Logger } from '@nestjs/common';
import { Common } from '../common/common';
import Redis from 'ioredis';
import { RedisService } from '@liaoliaots/nestjs-redis';
import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm';
import { Users } from '../../module/Users';
import { EntityManager, Repository } from 'typeorm';
import {
  RegisterInterface,
  SignInInterface,
  VerifyInterface,
} from './interface/user.interface';
import { MD5 } from 'crypto-js';
import * as moment from 'moment';
import { Utils } from '../../@nt';
import { RedisConfig } from '../../@nt/config';
import { VerificationCodes } from '../../module/VerificationCodes';
import { CommonUtil } from '../../@nt/utils/commonUtil';

@Injectable()
export class UserService extends Common {
  private readonly redis: Redis | null;
  private readonly logger = new Logger(UserService.name);

  constructor(
    @InjectEntityManager() // 注入 EntityManager
    private readonly entityManager: EntityManager,
    @InjectRepository(Users)
    private readonly userRepository: Repository<Users>,
    @InjectRepository(VerificationCodes)
    private readonly verifyCodeRepository: Repository<VerificationCodes>,
    private readonly redisService: RedisService,
  ) {
    super();
    this.redis = this.redisService.getOrThrow();
  }

  /**
   * 注册新增用户
   * @param body
   */
  async create(body: RegisterInterface): Promise<any> {
    if (body.password !== body.confirmPassword) {
      return this.returnJson(1004, null, '两次输入的密码不一致，请重新输入');
    }

    const data: any = {
      email: body.email,
      password: MD5(body.password).toString(),
      createdAt: moment().unix(),
    };
    const where: any = { email: data.email };
    let user: Users = await this.userRepository.findOne({ where });
    if (user) {
      return this.returnJson(1007, null, '该邮箱已被注册，请更换邮箱');
    }
    user = await this.userRepository.save(data);
    if (user) {
      this.logger.log(`用户注册成功: ${JSON.stringify(user)}`);
      const tokenData = await Utils.Secret.encrypt(user.id);
      const infoData: any = {
        id: user.id,
        email: user.email,
        role: user.role,
        isVerified: user.isVerified,
        accessToken: tokenData,
      };
      const accessTokenData = await Utils.JwtUtils.get(infoData, tokenData, {});
      infoData.token = tokenData;
      infoData.accessToken = accessTokenData;
      // this.redis.setex(
      //   `${RedisConfig.session}${user.id}`,
      //   86400,
      //   JSON.stringify(infoData),
      // );
      const returnData: any = {
        token: tokenData,
        accessToken: accessTokenData,
      };
      return this.returnJson(0, returnData, '注册成功');
    }
    return this.returnJson(1005, null, '注册失败');
  }

  /**
   * 登录
   * @param body
   */
  async signIn(body: SignInInterface): Promise<any> {
    const where: any = {
      email: body.email,
    };
    const user: Users = await this.userRepository.findOne({ where });
    if (user) {
      if (user.password !== MD5(body.password).toString()) {
        return this.returnJson(1008, null, '密码错误，请重试');
      }
    }
    const tokenData = await Utils.Secret.encrypt(user.id);
    const infoData: any = {
      id: user.id,
      email: user.email,
      role: user.role,
      isVerified: user.isVerified,
      accessToken: tokenData,
    };
    const accessTokenData = await Utils.JwtUtils.get(infoData, tokenData, {});
    infoData.token = tokenData;
    infoData.accessToken = accessTokenData;
    // this.redis.setex(
    //   `${RedisConfig.session}${user.id}`,
    //   86400,
    //   JSON.stringify(infoData),
    // );
    const returnData: any = { token: tokenData, accessToken: accessTokenData };
    return this.returnJson(0, returnData, '登录成功');
  }

  /**
   * 验证邮箱
   * @param body
   * @param user
   */
  async verifyEmail(body: VerifyInterface, user: any): Promise<any> {
    this.logger.log(JSON.stringify(user));
    const where: any = {
      id: user.id,
    };
    const userInfo: Users = await this.userRepository.findOne({ where });
    if (userInfo) {
      let verifyCode: any = await this.redis.get(
        `${RedisConfig.verifyCode}${userInfo.email}`,
      );
      if (!verifyCode) {
        verifyCode = await this.verifyCodeRepository.findOne({
          where: { email: userInfo.email, status: 0 },
        });
        if (!verifyCode) {
          return this.returnJson(-1, null, '验证码已过期，请重新获取');
        }
      } else {
        verifyCode = JSON.parse(verifyCode);
      }
      if (verifyCode.code !== body.code) {
        return this.returnJson(-1, null, '验证码错误，请重新输入');
      }
      try {
        await this.entityManager.transaction(
          async (transactionalEntityManager) => {
            await transactionalEntityManager
              .getRepository(VerificationCodes)
              .update(
                { email: userInfo.email, code: body.code, status: 0 },
                { status: 1 },
              );
            await transactionalEntityManager
              .getRepository(Users)
              .update({ id: user.id }, { isVerified: 1 });
          },
        );
        return this.returnJson(0, true, '验证成功');
      } catch (error) {
        this.logger.error(error);
        return this.returnJson(-1, null, '验证失败，请重试');
      }
    }
    return this.returnJson(-1, null, '验证失败，请重试');
  }
}
